理解和实施 Paxos、Raft 和 PBFT 等共识算法,在全球范围内构建高度可靠和容错的分布式系统的综合指南。(简体/繁體)
分布式系统:驾驭共识算法实现的复杂性(简体/繁體)
在现代技术广阔而互联的领域中,分布式系统构成了我们日常使用的几乎所有关键服务的支柱。 从全球金融网络和云基础设施到实时通信平台和企业应用程序,这些系统旨在跨多个独立的计算节点运行。 虽然提供了无与伦比的可扩展性、弹性和可用性,但这种分布带来了一个深刻的挑战:即使某些节点不可避免地发生故障,也要在所有参与节点上保持一致且双方同意的状态。 这就是共识算法的领域。
共识算法是分布式环境中数据完整性和运营连续性的沉默守护者。 它们使一组机器能够就单个值、操作顺序或状态转换达成一致,而不管网络延迟、节点崩溃甚至恶意行为如何。 没有它们,我们期望从数字世界获得的可靠性将会崩溃。 本综合指南深入研究了共识算法的复杂世界,探讨了它们的基本原理,检查了领先的实现,并为它们在现实世界分布式系统中的部署提供了实用的见解。
分布式共识的根本挑战(简体/繁體)
构建一个健壮的分布式系统本质上是复杂的。 核心困难在于网络的异步性质,消息可能被延迟、丢失或重新排序,并且节点可能独立失败。 考虑这样一种情况:多个服务器需要就特定事务是否已提交达成一致。 如果某些服务器报告成功,而另一些服务器报告失败,则系统的状态变得模糊,导致数据不一致和潜在的操作混乱。
CAP 定理及其相关性(简体/繁體)
分布式系统中的一个基本概念是 CAP 定理,它指出分布式数据存储只能同时保证以下三个属性中的两个:
- 一致性 (Consistency): 每次读取都会收到最近的写入或错误。
- 可用性 (Availability): 每个请求都会收到响应,但不保证它是最近的写入。
- 分区容错性 (Partition Tolerance): 即使任意网络故障(分区)导致节点之间丢失消息,系统也能继续运行。
实际上,在任何足够大规模的分布式系统中,网络分区都是不可避免的。 因此,设计人员必须始终选择分区容错性 (P)。 这需要在一致性 (C) 和可用性 (A) 之间做出选择。 共识算法主要旨在即使在面对分区 (P) 的情况下也能维护一致性 (C),通常以在网络分裂期间牺牲可用性 (A) 为代价。 当设计数据完整性至关重要的系统(例如金融账本或配置管理服务)时,这种权衡至关重要。
分布式系统中的故障模型(简体/繁體)
了解系统可能遇到的故障类型对于设计有效的共识机制至关重要:
- 崩溃故障(Fail-Stop):一个节点只是停止运行。 它可能会崩溃并重新启动,但它不会发送不正确或误导性的消息。 这是最常见且最容易处理的故障。
- 崩溃恢复故障:类似于崩溃故障,但节点可以从崩溃中恢复并重新加入系统,如果处理不当,可能会处于过时的状态。
- 遗漏故障:一个节点无法发送或接收消息,或者丢失消息。 这可能是由于网络问题或软件错误造成的。
- 拜占庭故障:最严重和最复杂。 节点可以任意行为,发送恶意或误导性消息,与其他故障节点勾结,甚至主动试图破坏系统。 这些故障通常在高度敏感的环境中考虑,例如区块链或军事应用。
FLP 不可能性结果(简体/繁體)
一个令人清醒的理论结果是,FLP 不可能性定理(Fischer、Lynch、Paterson,1985 年)指出,在异步分布式系统中,如果即使一个进程崩溃,也不可能保证共识。 该定理突出了实现共识的内在难度,并强调了为什么实际算法通常会对网络同步性做出假设(例如,在有界时间内传递消息),或者依赖随机化和超时来使进展在所有场景中都是概率性的而不是确定性的。 这意味着虽然可以设计一个系统以非常高的概率达成共识,但在完全异步、容易出错的环境中绝对确定性在理论上是无法实现的。
共识算法中的核心概念(简体/繁體)
尽管存在这些挑战,但实际的共识算法是必不可少的。 它们通常遵循一组核心属性:
- 一致性 (Agreement): 所有非故障进程最终都对同一值达成一致。
- 有效性 (Validity): 如果就一个值
v达成一致,那么v必须是由某个进程提出的。 - 终止性 (Termination): 所有非故障进程最终都会决定一个值。
- 完整性 (Integrity): 每个非故障进程最多决定一个值。
除了这些基本属性之外,还通常采用以下几种机制:
- 领导者选举 (Leader Election): 许多共识算法指定一个“领导者”负责提出值并协调一致过程。 如果领导者失败,则必须选举一个新的领导者。 这简化了协调,但如果处理不当,会引入潜在的单点故障(对于提出,而不是对于同意)。
- 仲裁 (Quorums): 通常,当“仲裁”(多数或特定子集)的节点确认提案时,而不是要求每个节点都同意,就达成共识。 这允许系统即使在某些节点关闭或速度较慢的情况下也能取得进展。 仔细选择仲裁大小,以确保任何两个相交的仲裁将始终共享至少一个公共节点,从而防止冲突的决策。
- 日志复制 (Log Replication): 共识算法通常通过跨多台机器复制一系列命令(日志)来运行。 每个命令一旦通过共识达成一致,就会附加到日志中。 然后,此日志用作“状态机”的确定性输入,确保所有副本以相同的顺序处理命令并达到相同的状态。
流行的共识算法及其实现(简体/繁體)
虽然共识的理论格局广阔,但一些算法已成为实际分布式系统中的主要解决方案。 每个都提供了复杂性、性能和容错特性的不同平衡。
Paxos:分布式共识的教父(简体/繁體)
Paxos 由 Leslie Lamport 于 1990 年首次发表(尽管直到很久以后才被广泛理解),可以说是最具影响力和最广泛研究的共识算法。 它以能够在具有崩溃进程的异步网络中达成共识而闻名,前提是大多数进程都在运行。 然而,它的正式描述非常难以理解,导致了这样一句话:“一旦你理解了它,Paxos 就很简单了。”
Paxos 的工作原理(简化)(简体/繁體)
Paxos 定义了三种类型的参与者:
- 提议者 (Proposers): 提出要达成一致的值。
- 接受者 (Acceptors): 对提议的值进行投票。 他们存储他们见过的最高提议编号和他们接受的值。
- 学习者 (Learners): 发现已选择哪个值。
该算法分两个主要阶段进行:
-
阶段 1(准备):
- 1a(准备):提议者向大多数接受者发送带有新的、全局唯一的提议编号
n的“准备”消息。 - 1b(承诺):接受者在收到准备消息
(n)后,会回复“承诺”以忽略任何编号小于n的未来提议。 如果它已经接受了先前提议的值,则会在其响应中包含编号最高的接受值(v_accepted)及其提议编号(n_accepted)。
- 1a(准备):提议者向大多数接受者发送带有新的、全局唯一的提议编号
-
阶段 2(接受):
- 2a(接受):如果提议者收到来自大多数接受者的承诺,则它为其提议选择一个值
v。 如果任何接受者报告了先前接受的值v_accepted,则提议者必须选择与最高n_accepted相关联的值。 否则,它可以提出自己的值。 然后,它向同一多数接受者发送一条“接受”消息,其中包含提议编号n和选定的值v。 - 2b(已接受):接受者在收到接受消息
(n, v)后,如果它没有承诺忽略编号小于n的提议,则接受该值v。 然后,它会将接受的值通知学习者。
- 2a(接受):如果提议者收到来自大多数接受者的承诺,则它为其提议选择一个值
Paxos 的优点和缺点(简体/繁體)
- 优点:高度容错(可以容忍
2f+1个节点中的f个崩溃故障)。 即使在网络分区期间也能保证安全性(永远不会做出错误的决定)。 可以在没有固定领导者的情况下取得进展(尽管领导者选举简化了它)。 - 缺点:极其难以理解和正确实现。 如果没有特定的优化(例如,像 Multi-Paxos 中那样使用杰出的领导者),可能会出现活性问题(例如,重复的领导者选举,导致饥饿)。
实际实现和变体(简体/繁體)
由于其复杂性,很少直接实现纯 Paxos。 相反,系统通常使用变体,例如 Multi-Paxos,它通过让稳定的领导者顺序提出多个值,来分摊跨多个共识轮次的领导者选举开销。 受 Paxos(或其衍生物)影响或直接使用 Paxos(或其衍生物)的系统示例包括 Google 的 Chubby 锁服务、Apache ZooKeeper(使用 ZAB,一种类 Paxos 算法)以及各种分布式数据库系统。
Raft:易于理解的共识(简体/繁體)
Raft 是由 Diego Ongaro 和 John Ousterhout 在斯坦福大学开发的,其明确目标是“可理解”。 虽然 Paxos 专注于共识的理论最小值,但 Raft 优先考虑一种更结构化和直观的方法,使其更容易实现和推理。
Raft 的工作原理(简体/繁體)
Raft 通过为其节点定义明确的角色和简单的状态转换来运行:
- 领导者 (Leader): 负责处理所有客户端请求、提出日志条目并将它们复制到关注者的主节点。 一次只有一个领导者。
- 关注者 (Follower): 仅响应来自领导者的请求并为候选人投票的被动节点。
- 候选人 (Candidate): 关注者在认为领导者已失败时转换到的状态,启动新的领导者选举。
Raft 通过两种关键机制达成共识:
- 领导者选举 (Leader Election): 当关注者在一定超时时间内没有收到来自领导者的消息时,它会成为候选人。 它会递增其当前任期(逻辑时钟)并为自己投票。 然后,它向其他节点发送“RequestVote”RPC。 如果它收到来自多数的投票,它将成为新的领导者。 如果另一个节点成为领导者或发生分裂投票,则会开始新的选举任期。
- 日志复制 (Log Replication): 领导者当选后,它会收到客户端命令并将它们附加到其本地日志。 然后,它向所有关注者发送“AppendEntries”RPC 以复制这些条目。 一旦领导者将其复制到大多数关注者,日志条目就会被提交。 只有已提交的条目才会应用于状态机。
Raft 的优点和缺点(简体/繁體)
- 优点:比 Paxos 更容易理解和实现。 强大的领导者模型简化了客户端交互和日志管理。 保证在崩溃故障下的安全性和活性。
- 缺点:强大的领导者可能是写密集型工作负载的瓶颈(尽管这对于许多用例来说通常是可以接受的)。 需要一个稳定的领导者才能取得进展,这可能会受到频繁的网络分区或领导者故障的影响。
Raft 的实际实现(简体/繁體)
Raft 的可理解性设计使其得到广泛采用。 突出的例子包括:
- etcd: Kubernetes 用于集群协调和状态管理的分布式键值存储。
- Consul: 一种服务网格解决方案,它使用 Raft 为其高度可用且一致的服务发现和配置数据存储。
- cockroachDB: 一种分布式 SQL 数据库,它使用基于 Raft 的方法来实现其底层存储和复制。
- HashiCorp Nomad: 一种工作负载编排器,它使用 Raft 来协调其代理。
ZAB (ZooKeeper Atomic Broadcast)(简体/繁體)
ZAB 是 Apache ZooKeeper 核心的共识算法,ZooKeeper 是一种广泛使用的分布式协调服务。 虽然经常与 Paxos 相提并论,但 ZAB 专门为 ZooKeeper 提供状态更改的有序、可靠广播和管理领导者选举的要求而量身定制。
ZAB 的工作原理(简体/繁體)
ZAB 旨在保持所有 ZooKeeper 副本的状态同步。 它通过一系列阶段来实现这一点:
- 领导者选举 (Leader Election): ZooKeeper 使用原子广播协议的变体(包括领导者选举)来确保始终只有一个领导者处于活动状态。 当当前领导者失败时,选举过程开始,节点投票选出新的领导者,通常是日志最新的节点。
- 发现 (Discovery): 领导者当选后,它开始发现阶段,以从其关注者那里确定最新状态。 关注者将其最高日志 ID 发送给领导者。
- 同步 (Synchronization): 然后,领导者将其状态与关注者同步,发送任何缺失的事务以使其保持最新状态。
- 广播 (Broadcast): 同步后,系统进入广播阶段。 领导者提出新的事务(客户端写入),并将这些提案广播给关注者。 一旦大多数关注者确认该提案,领导者就会提交该提案并广播提交消息。 然后,关注者将已提交的事务应用于其本地状态。
ZAB 的主要特征(简体/繁體)
- 专注于总订单广播,确保所有更新以相同的顺序在所有副本上处理。
- 强调领导者稳定性以保持高吞吐量。
- 将领导者选举和状态同步集成为核心组件。
ZAB 的实际使用(简体/繁體)
Apache ZooKeeper 为许多其他分布式系统提供了一项基础服务,包括 Apache Kafka、Hadoop、HBase 和 Solr,提供诸如分布式配置、领导者选举和命名等服务。 它的可靠性直接源于健壮的 ZAB 协议。
拜占庭容错 (BFT) 算法(简体/繁體)
虽然 Paxos、Raft 和 ZAB 主要处理崩溃故障,但某些环境需要针对 拜占庭故障的弹性,在这种情况下,节点可能会恶意或任意行为。 这在非信任环境中尤其相关,例如公共区块链或高度敏感的政府/军事系统。
实用拜占庭容错 (PBFT)(简体/繁體)
PBFT 由 Castro 和 Liskov 于 1999 年提出,是最著名的和实用的 BFT 算法之一。 它允许分布式系统达成共识,即使最多三分之一的节点是拜占庭式(恶意或有故障)。
PBFT 的工作原理(简化)(简体/繁體)
PBFT 在一系列视图中运行,每个视图都有一个指定的主节点(领导者)。 当主节点失败或被怀疑有故障时,会启动视图更改协议以选举新的主节点。
客户端请求的正常操作涉及几个阶段:
- 客户端请求 (Client Request): 客户端向主节点发送请求。
- 预准备 (Pre-Prepare): 主节点将序列号分配给请求,并将“预准备”消息多播到所有备份(关注者)节点。 这为请求建立了一个初始顺序。
- 准备 (Prepare): 收到预准备消息后,备份会验证其真实性,然后将“准备”消息多播到包括主节点在内的所有其他副本。 此阶段确保所有非故障副本都同意请求的顺序。
-
提交 (Commit): 一旦副本收到特定请求的
2f+1条准备消息(包括其自身)(其中f是故障节点的最大数量),它会将“提交”消息多播到所有其他副本。 此阶段确保请求将被提交。 -
回复 (Reply): 收到
2f+1条提交消息后,副本会执行客户端请求并将“回复”发送回客户端。 客户端等待f+1个相同的回复,然后才认为操作成功。
PBFT 的优点和缺点(简体/繁體)
- 优点:容忍拜占庭故障,即使在恶意参与者的情况下也能确保强大的安全保证。 确定性共识(没有概率确定性)。
- 缺点:大量的通信开销(每个共识轮次需要
O(n^2)条消息,其中n是副本的数量),限制了可扩展性。 高延迟。 复杂的实现。
PBFT 的实际实现(简体/繁體)
虽然由于其开销而在主流基础设施中不太常见,但 PBFT 及其衍生物在不能假设信任的环境中至关重要:
- Hyperledger Fabric: 一种许可区块链平台,它使用一种 PBFT 形式(或模块化共识服务)来进行事务排序和确定性。
- 各种区块链项目: 许多企业区块链和许可分布式账本技术 (DLT) 使用 BFT 算法或变体来实现已知但可能不值得信任的参与者之间的共识。
实施共识:实际考虑因素(简体/繁體)
选择和实施共识算法是一项重要的任务。 必须仔细考虑几个实际因素才能成功部署。
选择正确的算法(简体/繁體)
共识算法的选择在很大程度上取决于系统的具体要求:
- 容错要求: 你是否只需要容忍崩溃故障,或者你是否必须考虑拜占庭故障? 对于大多数企业应用程序,像 Raft 或 Paxos 这样的容错算法是足够的并且性能更高。 对于高度对抗性或非信任环境(例如,公共区块链),BFT 算法是必要的。
- 性能与一致性之间的权衡: 更高的一致性通常伴随着更高的延迟和更低的吞吐量。 了解你的应用程序对最终一致性与强一致性的容忍度。 Raft 为许多应用程序提供了良好的平衡。
- 易于实施和维护: Raft 的简单性使其成为新实现的热门选择。 Paxos 虽然功能强大,但众所周知很难正确实施。 考虑你的工程团队的技能组合和长期可维护性。
-
可扩展性需求: 你的集群将有多少个节点? 它们在地理位置上会分散多远? 具有
O(n^2)通信复杂性(如 PBFT)的算法无法扩展到数百或数千个节点,而基于领导者的算法可以更有效地管理更大的集群。
网络可靠性和超时(简体/繁體)
共识算法对网络条件高度敏感。 实施必须稳健地处理:
- 网络延迟: 延迟会减慢共识轮次,特别是对于需要多轮通信的算法。
- 数据包丢失: 消息可能会丢失。 算法必须使用重试和确认来确保可靠的消息传递。
- 网络分区: 系统必须能够检测和从分区中恢复,在拆分期间可能会牺牲可用性以换取一致性。
- 自适应超时: 固定超时可能会出现问题。 动态自适应超时(例如,对于领导者选举)可以帮助系统在不同的网络负载和条件下更好地执行。
状态机复制 (SMR)(简体/繁體)
共识算法通常用于实现 状态机复制 (SMR)。 在 SMR 中,服务的所有副本都以相同的初始状态启动,并以相同的顺序处理相同的客户端命令序列。 如果命令是确定性的,则所有副本都将通过相同的状态序列转换,从而确保一致性。 共识算法的作用是就应用于状态机的命令的总顺序达成一致。 这种方法是构建容错服务的基础,例如复制数据库、分布式锁和配置服务。
监控和可观察性(简体/繁體)
使用共识算法运行分布式系统需要广泛的监控。 要跟踪的关键指标包括:
- 领导者状态: 哪个节点是当前领导者? 它担任领导者有多久了?
- 日志复制进度: 关注者是否落后于领导者的日志? 复制滞后是多少?
- 共识轮次延迟: 提交新条目需要多长时间?
- 网络延迟和数据包丢失: 在所有节点之间,尤其是在领导者和关注者之间。
- 节点运行状况: 所有参与者的 CPU、内存、磁盘 I/O。
基于这些指标的有效警报对于快速诊断和解决问题至关重要,从而防止由于共识失败导致的服务中断。
安全影响(简体/繁體)
虽然共识算法可确保一致性,但它们本身并不提供安全性。 实施必须考虑:
- 身份验证: 确保只有授权节点才能参与共识过程。
- 授权: 定义每个节点被允许执行的操作(例如,提出值、投票)。
- 加密: 保护节点之间的通信以防止窃听或篡改。
- 完整性: 使用数字签名或消息身份验证码来确保消息在传输过程中未被更改,这对于 BFT 系统尤为重要。
高级主题和未来趋势(简体/繁體)
分布式共识领域在不断发展,不断涌现出新的研究和挑战。
动态成员资格(简体/繁體)
许多共识算法假设一组静态的参与节点。 但是,现实世界的系统通常需要动态成员资格更改(添加或删除节点)以向上或向下扩展,或更换发生故障的硬件。 安全地更改集群成员资格同时保持一致性是一个复杂的问题,像 Raft 这样的算法为此制定了明确的多阶段协议。
地理上分布的部署(WAN 延迟)(简体/繁體)
跨地理上分散的数据中心部署共识算法会带来显着的广域网 (WAN) 延迟,这会严重影响性能。 正在探索针对 WAN 优化的 Paxos 或 Raft 变体(例如,在本地区域内使用较小的仲裁以加快读取速度,或仔细放置领导者)等策略。 多区域部署通常涉及全球一致性和本地性能之间的权衡。
区块链共识机制(简体/繁體)
区块链技术的兴起重新激发了人们对共识的兴趣和创新。 公共区块链面临着一个独特的挑战:在没有中央权威的情况下,在一组庞大、动态且可能具有对抗性的未知参与者之间达成共识。 这导致了新的共识机制的开发:
- 工作量证明 (PoW): (例如,比特币、以太坊在“合并”之前)依靠计算难题来保护账本,从而使恶意行为者难以重写历史。
- 权益证明 (PoS): (例如,以太坊在“合并”之后、Solana、Cardano)验证者是根据他们“质押”作为抵押品的加密货币数量来选择的,从而激励诚实的行为。
- 委托权益证明 (DPoS): (例如,EOS、TRON)利益相关者选举有限数量的代表来验证交易。
- 有向无环图 (DAG): (例如,IOTA、Fantom)一种不同的数据结构允许并行处理事务,从而有可能在没有传统基于块的共识的情况下提供更高的吞吐量。
与传统的分布式系统共识相比,这些算法通常优先考虑不同的属性(例如,审查抵抗、去中心化、确定性),后者通常侧重于在受信任的有界节点集中实现强一致性和高可用性。
优化和变体(简体/繁體)
正在进行的研究继续改进现有算法并提出新的算法。 例子包括:
- Fast Paxos: 一种旨在通过允许在正常情况下在一轮通信中选择值来减少延迟的变体。
- Egalitarian Paxos: 旨在通过允许多个领导者或提议者在某些情况下无需协调即可同时运行来提高吞吐量。
- Generalized Paxos: 扩展 Paxos 以允许就值序列和任意状态机操作达成一致。
结论(简体/繁體)
共识算法是构建可靠分布式系统的基石。 虽然在概念上具有挑战性,但掌握它们对于任何冒险进入现代系统架构复杂性的专业人士来说都是必不可少的。 从 Paxos 严格的安全保证到 Raft 用户友好的设计,以及 PBFT 强大的容错能力,每种算法都提供了一组独特的权衡,以确保在不确定性面前保持一致性。
实施这些算法不仅仅是一项学术练习; 而是关于工程系统,这些系统可以承受网络和硬件故障的不可预测性,从而确保全球用户的数据完整性和持续运营。 随着分布式系统的不断发展,受到云计算、区块链以及对全球规模服务不断增长的需求的推动,共识算法的原理和实际应用将仍然是稳健且有弹性的系统设计的重中之重。 了解这些基本构建块使工程师能够创建下一代高度可用且一致的数字基础设施,为我们互联的世界提供服务。